<?php
namespace wxpay;

use think\facade\Log;

class Wxpay{

    // public $notify_url = 'http://'.$_SERVER['HTTP_HOST'].'/wap/order/notify';    //   回调地址

    public $config =[
        "appid"      => 'wxe4b77d2f0f456b9b',  //   公众号ID
        "mch_id"     => "1601872738",    //   商户号
        'notify_url' => '',
        "key"        => "GDDGxnm0769qweASDzxc889966774412",    //   微信支付 商户秘钥KEY
    ];

    public function __construct($type = 1)
    {
        $url = 'http://'.$_SERVER['HTTP_HOST'].'/index/order/callbackNotify';    //商品会员回调地址
        if($type == 2){
            $url = 'http://'.$_SERVER['HTTP_HOST'].'/index/activity/notify';    //活动支付回调地址
        }
        if($type == 3){
            $url = 'http://'.$_SERVER['HTTP_HOST'].'/index/article/callbackNotify';    //文章支付回调地址
        }
        if($type == 4){
            $url = 'http://'.$_SERVER['HTTP_HOST'].'/index/poster/callbackNotify';    //海报支付回调地址
        }
        if($type == 5){
            $url = 'http://'.$_SERVER['HTTP_HOST'].'/index/activity/callbackNotify';    //发布活动支付回调地址
        }
        if($type == 6){
            $url = 'http://'.$_SERVER['HTTP_HOST'].'/index/user/callbackNotify';    //企业/社群认证支付回调地址
        }
        if($type == 7){
            $url = 'https://'.$_SERVER['HTTP_HOST'].'/wxapp/api/pay_notify';//媒介交易中心 充值回调
            $this->config['appid'] = 'wxf8b5cc76a8fa700b'; //小程序appid  
        }
        if($type == 8){
            $url = 'https://'.$_SERVER['HTTP_HOST'].'/wxapp/api/wxpay_notify';//媒介交易中心 充值回调
            $this->config['appid'] = 'wxf8b5cc76a8fa700b'; //小程序appid  
        }
        if($type == 9){
            $url = 'https://'.$_SERVER['HTTP_HOST'].'/users/callbackNotify';//云links小程序 回调
            $this->config['appid'] = 'wxf8b5cc76a8fa700b'; //小程序appid
        }
        if($type == 10){
            $url = 'https://'.$_SERVER['HTTP_HOST'].'/users/publicCallbackNotify';//云links公众号 回调
        }
        $this->config['notify_url'] = $url;
    }


    public function index($param,$openid,$type = 0)
    {

        $order=array(
            'body'          => $param['body'],// 商品描述
            'total_fee'     => intval($param['total']*100),// 订单金额  以(分)为单位
            // 'total_fee'     => 1,
            'out_trade_no'  => $param['order_sn'],// 订单号
            'trade_type'    => 'JSAPI',// JSAPI公众号支付
            'openid'        => $openid,// 获取到的openid
        );
        $userip = $param['userip'];
        // 统一下单 获取prepay_id
        $unified_order=$this->unifiedOrder($order,$userip,$type);

        // 获取当前时间戳
        $time=time();
        // 组合jssdk需要用到的数据
        $data=array(
            'appId'     =>$this->config['appid'], //appid
            'timeStamp' =>strval($time), //时间戳
            'nonceStr'  =>$unified_order['nonce_str'],// 随机字符串
            'package'   =>'prepay_id='.$unified_order['prepay_id'],// 预支付交易会话标识
            'signType'  =>'MD5'      //加密方式
        );
        // Log::record($unified_order,'error');
        // 生成签名
        $data['paySign']=$this->makeSign($data);
        return $data;
    }

    /**
     * 统一下单
     * @param  array $order 订单 必须包含支付所需要的参数 body(产品描述)、total_fee(订单金额)、out_trade_no(订单号)、product_id(产品id)、trade_type(类型：JSAPI，NATIVE，APP)
     */
    public function unifiedOrder($order,$userip,$type)
    {
        $config=array(
            'appid'             => $this->config['appid'], //appid
            'mch_id'            => $this->config['mch_id'], //商户号ID
            'nonce_str'         => $this->getNonceStr(),
            'spbill_create_ip'  => $userip,  //你的IP
            'notify_url'        => $type == 0?$this->config['notify_url'] : $this->config['notify_recharge'],
            //'notify_url'        =>$url
            );

        // 合并配置数据和订单数据
        $data=array_merge($order,$config);
        // 生成签名
        $sign=$this->makeSign($data);
        $data['sign']=$sign;
        //转换成xml
        $xml=$this->toXml($data);
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';//接收xml数据的文件
        $header[] = "Content-type: text/xml";//定义content-type为xml,注意是数组
        $ch = curl_init ($url);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 兼容本地没有指定curl.cainfo路径的错误
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        $response = curl_exec($ch);
        if(curl_errno($ch)){
            // 显示报错信息；终止继续执行
            die(curl_error($ch));
        }
        curl_close($ch);
        //转换成数组
        $result=$this->toArray($response);
        //dump($result);
        // Log::record($result,'error');
        // 显示错误信息
        if ($result['return_code']=='FAIL') {
            die($result['return_msg']);
        }
        $result['sign']=$sign;
        $result['nonce_str']=$this->getNonceStr();
        return $result;
    }
    /**
     * 生成签名
     * @return 签名，本函数不覆盖sign成员变量，如要设置签名需要调用SetSign方法赋值
     */
    public function makeSign($data)
    {
        // 去空
        $data=array_filter($data);
        //签名步骤一：按字典序排序参数
        ksort($data);
        //将数组转成url形式
        $string_a=http_build_query($data);
        $string_a=urldecode($string_a);
        //签名步骤二：在string后加入KEY
        $string_sign_temp=$string_a."&key=".$this->config['key'];
        //签名步骤三：MD5加密
        $sign = md5($string_sign_temp);
        // 签名步骤四：所有字符转为大写
        $result=strtoupper($sign);
        return $result;
    }

    /**
     * 将xml转为array
     * @param  string $xml xml字符串
     * @return array       转换得到的数组
     */
    public function toArray($xml){
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $result= json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $result;
    }

    /**
     *
     * 产生随机字符串，不长于32位
     * @param int $length
     * @return 产生的随机字符串
     */
    public function getNonceStr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {
            $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }

    /**
     * 输出xml字符
     * @throws Exception
     */
    public function toXml($data){
        if(!is_array($data) || count($data) <= 0){
            throw new Exception("数组数据异常！");
        }
        $xml = "<xml>";
        foreach ($data as $key=>$val){
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
    }

    /**
     * 验证
     * @return array 返回数组格式的notify数据
     */
    public function notify()
    {
        // 获取xml
        $xml=file_get_contents('php://input');
        // 转成php数组
        $data=$this->toArray($xml);
        // 保存原sign
        $data_sign=$data['sign'];
        // sign不参与签名
        unset($data['sign']);
        $sign=$this->makeSign($data);
        // 判断签名是否正确  判断支付状态
        if ($sign===$data_sign && $data['return_code']=='SUCCESS' && $data['result_code']=='SUCCESS') {
            $result=$data;
        }else{
            $result=false;
        }
        // 返回状态给微信服务器
        if ($result) {
            $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }else{
            $str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>';
        }

        // file_put_contents("./Public/aaa.text",$result);
        // echo $str;
        return $result;
    }

    public function https_request($url, $data = null)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)){
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
         // var_dump($output);
        curl_close($curl);
        return $output;
    }

    // 小程序 appID 和 appSecret 获取 token
    private function getToken()
    {
        $appid='wxf8b5cc76a8fa700b';
        $appsecret='db9429875f9b630fa21ef448b5d6eb94';
        $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $appid . '&secret=' . $appsecret;
        $html = file_get_contents($url);
        $output = json_decode($html, true);
        $access_token = $output['access_token'];
        return $access_token;
    }
    public function sendMessage_status($proopenid='',$data=[])//订单状态模板
    {
      $token = $this->getToken();
      $post = [];
      $post['touser'] = $proopenid;
      $post['page'] = '/pages/price/incomelog';//消息跳转页面url
      $post['emphasis_keyword'] = 'phrase3.DATA';//需要放大自提的字段
      $post['color'] = '#173177';
      $post['template_id'] = 'T4GLUufGSz5Q2NSrDYABgavHZ9yb_I4zWGZXEhNB2E4';
      $post['form_id'] = $data['form_id'];
      $post['data'] = [
          'character_string1'=>['value'=>$data['order_no'],'color'=>'#173177'],
          'thing2'=>['value'=>$data['type_name'],'color'=>'#173177'],
          'phrase3'=>['value'=>$data['status_name'],'color'=>'#173177'],
          'time4'=>['value'=>date('Y-m-d H:i:s'),'color'=>'#173177'],
          'thing5'=>['value'=>$data['msg'],'color'=>'#173177']
      ];
      $url = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token='.$token;
      $re = $this->curl_url($url,$post);
      return $re;
  }
  public function sendMessage_withdrawal($proopenid='',$data=[])//提现审核模板
    {
      $token = $this->getToken();
      $post = [];
      $post['touser'] = $proopenid;
      $post['page'] = '/pages/person/withdrawallog';//消息跳转页面url
      $post['emphasis_keyword'] = 'phrase2.DATA';//需要放大自提的字段
      $post['color'] = '#173177';
      $post['template_id'] = 'W8JS8mZDmYoJdW7vYckot_gmPHLEwhJi3jqP3-mPQ-Y';
      // $post['form_id'] = $data['form_id'];
      $post['data'] = [
          'amount1'=>['value'=>$data['money'],'color'=>'#173177'],
          'phrase2'=>['value'=>$data['status_name'],'color'=>'#173177'],
      ];

      $url = 'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token='.$token;
      $re = $this->curl_url($url,$post);
      return $re;
  }

  private function curl_url($url, $json)
  {
      $body = json_encode($json);
      $headers = array("Content-type: application/json;charset=UTF-8", "Accept: application/json", "Cache-Control: no-cache", "Pragma: no-cache");
      $ch = curl_init($url);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_POST, 1);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
      curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
      $result = curl_exec($ch);
      curl_close($ch);

      return $result;
  }

}
